package net.sf.rose.business.service;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Collections;

import net.sf.rose.business.bean.base.FileBean;
import net.sf.rose.business.bean.control.MenuBean;
import net.sf.rose.business.bean.control.menu.ComparatorMenu;
import net.sf.rose.exception.SystemErrorCode;
import net.sf.rose.exception.SystemException;
import net.sf.rose.jdbc.KeyGenerator;
import net.sf.rose.jdbc.GenericDAO;
import net.sf.rose.jdbc.QueryBeanSQL;
import net.sf.rose.jdbc.UserBean;
import net.sf.rose.jdbc.service.DataBaseFactory;
import net.sf.rose.jdbc.service.Service;
import net.sf.rose.util.DateUtil;

import org.apache.log4j.Logger;
import org.simpleframework.xml.Element;
import org.simpleframework.xml.Serializer;
import org.simpleframework.xml.core.Persister;

/**
 * @author fengjian
 * @since 2014/05/25
 */
public class MenuSevice {

	private static Logger logger = Logger.getLogger(MenuSevice.class);

	/** 存储在数据库中的名称 */
	private static String NAME = "menu_meta";

	/** 存储在数据库中的分类名称 */
	private static String SORT = "config";

	/** 本类的单例 */
	private static MenuSevice service = null;

	/** 数据类的单例 */
	private static FileBean fileBean = null;

	static {
		Service s = DataBaseFactory.getService();
		UserBean user = new UserBean();
		user.setUserName("system");
		s.setUser(user);
		GenericDAO dao = new GenericDAO(s);
		QueryBeanSQL query = new QueryBeanSQL(s);
		fileBean = new FileBean();
		fileBean.setCode(NAME);
		fileBean.setFileSort(SORT);
		try {
			query.createListSql(fileBean);
			Object obj = dao.load(query);
			if (obj != null) {
				fileBean = (FileBean) obj;
				InputStream in = fileBean.getFile();
				if (in != null) {
					Serializer serializer = new Persister();
					service = serializer.read(MenuSevice.class, in);
				}
			}
			if (service == null) {
				service = new MenuSevice();
				MenuBean menu = new MenuBean();
				menu.setId("100");
				menu.setCode("root");
				menu.setText("根目录");
				service.setMenuBean(menu);
			}
		} catch (SystemException e) {
			throw e;
		} catch (Exception e) {
			String message = "菜单初始化失败！";
			logger.error(message, e);
			throw new SystemException(message, SystemErrorCode.APPLICATION_ERROR);
		} finally {
			s.close();
		}
	}

	/**
	 * 
	 */
	public static void save(UserBean user) {
		// 将菜单按照顺序排序
		service.formatSort(service.menu);
		Service s = DataBaseFactory.getService();
		GenericDAO dao = new GenericDAO(s);
		QueryBeanSQL query = new QueryBeanSQL(s);
		try {
			Serializer serializer = new Persister();
			File file = new File(System.getenv("TEMP"), KeyGenerator.getUID());
			serializer.write(service, file);
			InputStream in = new FileInputStream(file);
			fileBean.setFile(in);
			if (fileBean.getFileID() == null) {
				fileBean.setFileID(KeyGenerator.getUID());
				fileBean.setCreateUser(user.getUserName());
				fileBean.setCreateTime(DateUtil.getTimestamp());
				query.createInsertSql(fileBean);
			} else {
				fileBean.setUpdateUser(user.getUserName());
				fileBean.setUpdateTime(DateUtil.getTimestamp());
				query.createUpdateSql(fileBean);
			}
			dao.update(query);
			s.commit();
		} catch (SystemException e) {
			throw e;
		} catch (Exception e) {
			String message = "菜单保存失败！";
			logger.error(message, e);
			throw new SystemException(message, SystemErrorCode.APPLICATION_ERROR);
		} finally {
			s.close();
		}
	}

	/**
	 * 
	 */
	public static void input(InputStream in) {
		try {
			if (in != null) {
				Serializer serializer = new Persister();
				service = serializer.read(MenuSevice.class, in);
				logger.info("成功地从导入文件中读取了数据字典！");
			}
		} catch (Exception e) {
			String message = "数据字典导入失败！";
			logger.error(message, e);
			throw new SystemException(message, SystemErrorCode.APPLICATION_ERROR);
		}
	}

	/**
	 * 
	 */
	public static File output() {
		try {
			Serializer serializer = new Persister();
			File file = new File(System.getenv("TEMP"), KeyGenerator.getUID());
			serializer.write(service, file);
			return file;
		} catch (Exception e) {
			String message = "数据字典导出失败！";
			logger.error(message, e);
			throw new SystemException(message, SystemErrorCode.APPLICATION_ERROR);
		}
	}

	public static MenuSevice getService() {
		return service;
	}

	@Element
	private MenuBean menu = null;

	public MenuBean getMenuBean() {
		return menu;
	}

	public void setMenuBean(MenuBean menu) {
		this.menu = menu;
	}

	private ComparatorMenu comparatorMenu = new ComparatorMenu();

	private void formatSort(MenuBean menu) {
		if (menu.getChildMenus().size() == 0) {
			return;
		}
		Collections.sort(menu.getChildMenus(), comparatorMenu);
		for (MenuBean m : menu.getChildMenus()) {
			formatSort(m);
		}
	}

	/**
	 * 功能:返回给出菜单的父菜单
	 * @param child - 当前菜单
	 * @return 父菜单
	 */
	public MenuBean getParent(MenuBean child) {
		String id = child.getId();
		if (id.length() < 7) {
			return service.menu;
		}
		id = id.substring(0, id.length() - 3);
		int length = id.length() / 3;
		int count = 2;
		String sid = id.substring(0, count * 3);
		MenuBean parent = menu;
		do {
			for (MenuBean p : parent.getChildMenus()) {
				if (p.getId().equals(sid)) {
					parent = p;
					break;
				}
			}
			if (count == length) {
				sid = null;
			} else {
				count++;
				sid = id.substring(0, count * 3);
			}
		} while (sid != null);
		return parent;
	}
	
	/**
	 * 功能:返回给出菜单的父菜单
	 * @param child - 当前菜单
	 * @return 父菜单
	 */
	public MenuBean getMenuBean(String id) {
		if (id.length() == 3) {
			return service.menu;
		}
		int length = id.length() / 3;
		int count = 2;
		String sid = null;
		MenuBean parent = menu;
		do {
			sid = id.substring(0, count * 3);
			for (MenuBean p : parent.getChildMenus()) {
				if (p.getId().equals(sid)) {
					parent = p;
					break;
				}
			}
			if (count == length) {
				sid = null;
			} else {
				count++;
			}
		} while (sid != null);
		if (count == length) {
			return parent;
		} else {
			return null;
		}
	}
}
